﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using OpenComposite.Base.Collections;
using OpenComposite.Base.Designer;
using OpenComposite.EII.Designer.Org.Forms;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.Repository;

namespace OpenComposite.EII.Designer.Org
{
	public class OrgSymbol : CollapsableSymbol
	{
		public OrgSymbol()
			: base()
		{
			init();
		}

		private void init()
		{
			this.BeginUpdate();

			this.Name = "Enterprise";

			this.Border = BorderType.RoundedRectangle;

			this.ExpandedBackColor = Color.White;
			this.ExpandedBackColor2 = Color.Silver;
			this.ExpandedBorderColor = Color.Black;
			this.ExpandedSize = new Size(170, 220);

			this.CollapsedBackColor = Color.White;
			this.CollapsedBackColor2 = Color.Silver;
			this.CollapsedBorderColor = Color.Black;
			this.CollapsedSize = new Size(170, 110);

			this.CollapseSign = CollapseSign.DoubleArrow;
			this.CollapseSignPosition = CollapseSignPosition.TopRight;

			this.BackBrushMode = BackgroundBrushMode.LinearGradient;
			this.BackLinearGradientMode = System.Drawing.Drawing2D.LinearGradientMode.Vertical;

			this.MinimumSize = new Size(170, 110);

			this.NameTextBox.AutoSize = false;

			this.AllowDrop = true;

			//context Menu
			this.ContextMenuStrip.Items.Add("Add Organizational Unit", Resources.png_org_unit, new EventHandler(onAddOrgUnit_Click));
			this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
			this.ContextMenuStrip.Items.Add("Add Role", Resources.png_users, new EventHandler(onAddRole_Click));
			this.ContextMenuStrip.Items.Add("Edit Roles", Resources.png_users, new EventHandler(onEditRoles_Click));

			_orgUnits = new OrgUnitChild();
			_orgUnits.Parent = this;
			_orgUnits.Location = new Point(Location.X, Location.Y + 20);
			_orgUnits.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
			_orgUnits.Visible = true;
			adjustUserSymbol();

			// structure

			this.EndUpdate();
		}

		public override void InitializeNew(IServiceProvider serviceProvider)
		{
			base.InitializeNew(serviceProvider);
		}

		public override void InitializeLoaded()
		{
			_orgUnitList = Global.Data.GetOrgUnitsByOrg(_orgID);
			_orgUnits.OrgUnits.Clear();
			_orgUnits.OrgUnits.AddRange(_orgUnitList);
			_orgUnits.IsCollapsed = this.IsCollapsed;
			base.InitializeLoaded();
		}

		private int _width = 0;
		private int _orgID = 2;
		private OrgUnitChild _orgUnits;
		private BindingListEx<OrganizationalUnit> _orgUnitList = new BindingListEx<OrganizationalUnit>();

		public int OrganisationID
		{
			get { return _orgID; }
			set { _orgID = value; }
		}

		#region Public Members

		#region Override

		#region Collapsing

		protected override void OnCollapsed(EventArgs e)
		{
			base.OnCollapsed(e);
			_orgUnits.Visible = true;
		}

		protected override void OnCollapsing(System.ComponentModel.CancelEventArgs e)
		{
			_orgUnits.IsCollapsed = true;
			base.OnCollapsing(e);
			adjustUserSymbol();
		}

		protected override void OnExpanded(EventArgs e)
		{
			base.OnExpanded(e);
			_orgUnits.Visible = true;
		}

		protected override void OnExpanding(System.ComponentModel.CancelEventArgs e)
		{
			_orgUnits.IsCollapsed = false;
			base.OnExpanding(e);
			adjustUserSymbol();

		}

		#endregion

		public override bool CanDrag
		{
			get { return true; }
		}

		public override bool IsDropAllowed(object obj, Point location, MouseButtons button)
		{
			return
				( button == MouseButtons.Right &&
				obj is OrgSymbol ||
				obj is OrgUnitSymbol ||
				obj is RoleSymbol ||
				obj is UserSymbol );
		}

		public override bool CheckMouseOver(Point location)
		{
			return base.CheckMouseOver(location);
		}

		public override void DropObject(object obj, Point location, MouseButtons button)
		{
			if ( obj is OrgUnitSymbol ) {
				DesignerControl ctrl = obj as DesignerControl;
				ctrl.Location = new Point(Location.X, Bounds.Bottom + 50);
				DesignerViewControl.DesignerControls.Add(ctrl);
				Route r = DesignerViewControl.AddRoute(this, ctrl);
				r.StartDockDirection = RouteDockDirection.Bottom;
				r.EndDockDirection = RouteDockDirection.Top;
				//ArrangeConnectedSymbols();
			} else {
				base.DropObject(obj, location, button);
			}
		}

		protected override void OnControlRemoved(DesignerControl ctrl)
		{
			base.OnControlRemoved(ctrl);
			ArrangeConnectedSymbols();
		}

		public override object GetDragObject(Point location, MouseButtons button)
		{
			return this;
		}

		public override void PaintBackground(PaintEventArgs pe)
		{
			base.PaintBackground(pe);

			Rectangle rc = this.ClientRectangle;
			Point pt = this.PointToDesignerView(new Point(rc.X, rc.Bottom - 16));
			pe.Graphics.DrawImage(Resources.png_org, pt.X, pt.Y);
		}

		public override bool IsDropAllowed(Type type, Point location, MouseButtons button)
		{
			return ( type == typeof(OrgUnitSymbol) );
		}

		public override Point GetRouteStart(RouteDockDirection dock, Route route)
		{
			return new Point(Location.X + Width / 2, Bounds.Bottom);
		}

		protected override void OnLocationChanged(EventArgs e)
		{
			base.OnLocationChanged(e);
			//if ( DesignerViewControl != null ) {
			//    ArrangeConnectedSymbols();
			//}
		}

		#endregion

		public void ArrangeConnectedSymbols(/*DesignerControl lastControl*/)
		{
			_width = 0;
			List<Route> connectedRoutes = new List<Route>();
			connectedRoutes = DesignerViewControl.DesignerControls.Routes.FindAll(new Predicate<Route>(findConnectedRoutes));
			//int width = ( ( connectedRoutes.Count - 1 ) * 180 ) / 2;
			int w = _width;
			w = ( w - Width - ( connectedRoutes.Count * 10 ) ) / 2;
			foreach ( Route route in connectedRoutes ) {
				int align = ( route.EndControl as OrgUnitSymbol ).ArrangedWidth;
				//if ( align != route.EndControl.Width ||
				//    align != route.EndControl.Width + 10 ) {
				route.EndControl.Location = new Point(( this.Location.X - w ) + align / 2, Bottom + 70);
				//} else {
				//route.EndControl.Location = new Point(this.Location.X - w, Bottom + 70);
				//}
				w -= align + 10;
			}
		}

		public override bool CreateRouteEnd(DesignerControl controlStart, out IConnector connector, out System.Drawing.Drawing2D.LineCap cap, out System.Drawing.Drawing2D.CustomLineCap customcap, out RouteDockDirection dockStart, out RouteDockDirection dockEnd, out bool useEndConnectorAsRouteEnd)
		{
			return base.CreateRouteEnd(controlStart, out connector, out cap, out customcap, out dockStart, out dockEnd, out useEndConnectorAsRouteEnd);
		}

		public override bool CreateRouteStart(DesignerControl controlEnd, out IConnector connector, out System.Drawing.Drawing2D.LineCap cap, out System.Drawing.Drawing2D.CustomLineCap customcap, out RouteDockDirection dockStart, out RouteDockDirection dockEnd, out bool useStartConnectorAsRouteStart)
		{
			return base.CreateRouteStart(controlEnd, out connector, out cap, out customcap, out dockStart, out dockEnd, out useStartConnectorAsRouteStart);
		}
		#endregion

		protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e)
		{
			base.OnMouseClick(e);
		}

		private bool findConnectedRoutes(Route route)
		{
			if ( route.StartControl == this ) {
				_width += ( route.EndControl as OrgUnitSymbol ).ArrangedWidth;
				return true;
			} else
				return false;
		}

		private void onAddOrgUnit_Click(object sender, EventArgs e)
		{
			int index = this.DesignerViewControl.AddDesignerControl(new OrgUnitSymbol());
			this.DesignerViewControl.DesignerControls[index].Location =
				new Point(Location.X, Location.Y + Height + 40);
			this.DesignerViewControl.AddRoute(this, DesignerViewControl.DesignerControls[index]);
		}

		private void onAddRole_Click(object sender, EventArgs e)
		{
			RepositoryService rpSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( rpSvc == null )
				throw new NullReferenceException("Repository Service not available.");

			IRepositoryItem parentItem = null;
			Role newEntry = rpSvc.GetNewItem<Role>(true, ref parentItem);
		}

		private void onEditRoles_Click(object sender, EventArgs e)
		{
			int index = this.DesignerViewControl.AddDesignerControl(new OrgUnitSymbol());
			this.DesignerViewControl.DesignerControls[index].Location =
				new Point(Location.X, Location.Y + Height + 40);
			this.DesignerViewControl.AddRoute(this, DesignerViewControl.DesignerControls[index]);
		}

		private void adjustUserSymbol()
		{
			_orgUnits.Height = this.Height - 60;
			_orgUnits.Width = this.Width - 10;
		}
	}
}
